package bingo.xml;

import java.lang.reflect.Field;
import java.util.Iterator;

import net.bingosoft.common.BeanHelper;
import net.bingosoft.common.util.ClassUtil;
import net.bingosoft.common.util.XMLUtil;

import org.dom4j.Element;
import org.dom4j.Node;

import bingo.xml.annotation.Alias;
import bingo.xml.annotation.ChildElement;
import bingo.xml.annotation.Ignore;
import bingo.xml.annotation.RootElement;
import bingo.xml.annotation.TextElement;


/**
 * Feb 27, 2009 3:26:57 PM
 * Author:yangdongyu(yangdy@bingosoft.net)
 * ReadMe:对象序列化工具,将一个java对象转换成xml字符串
 * ChangeLog:
 */
public class XMLSerializer {
	/**
	 * 将该图代表的对象转换成xml
	 */
	public static Node toXML(Object target) {
		Class<?> clazz = target.getClass();
		String alias = clazz.getSimpleName().toLowerCase();
		if(clazz.isAnnotationPresent(Alias.class)){
			alias = clazz.getAnnotation(Alias.class).value();
		}
		Element root = XMLUtil.createElement(alias);
		Field[] fields = clazz.getDeclaredFields();
		for(Field field : fields){
			if(field.isAnnotationPresent(Ignore.class)){
				continue;
			}
			String fieldName = field.getName();
			Object fieldvalue = null;
			try {
				fieldvalue = BeanHelper.getRawProperty(target, fieldName);
			} catch (IllegalArgumentException e) {
				throw e;
			} catch (Exception e) {
				throw new RuntimeException("读取对象属性时发生错误，请检查...",e);
			}
			if(fieldvalue != null){
				if(field.isAnnotationPresent(Alias.class)){
					fieldName = field.getAnnotation(Alias.class).value();
				}
				if(ClassUtil.isPrimitiveOrWrapper(fieldvalue.getClass()) || fieldvalue instanceof String){
					if(field.isAnnotationPresent(TextElement.class)){
						root.addText(fieldvalue.toString());
					}else if(field.isAnnotationPresent(ChildElement.class)){
						Element e = XMLUtil.createElement(fieldName);
						e.addText(fieldvalue.toString());
						root.add(e);
					}else{
						root.addAttribute(fieldName, fieldvalue.toString());
					}
				}else if(fieldvalue instanceof Iterable){
					Iterator<?> it = ((Iterable<?>)fieldvalue).iterator();
					Element e = XMLUtil.createElement(fieldName);
					while(it.hasNext()){
						e.add(toXML(it.next()));
					}
					root.add(e);
				}
			}

		}
		if(clazz.isAnnotationPresent(RootElement.class)){
			return XMLUtil.createDocument(root);
		}
		return root;
	}
	/**
	 * 将一个对象转换成XML
	 * @param target
	 * @return
	 */
	public static String serializeToXML(Object target){
		return toXML(target).asXML();
	}
}
